package com.eorchis.module.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.apache.tools.zip.ZipOutputStream;

/**
 * 
 * 类名： ZipUtil.java<br>
 * 描述：压缩/解压缩zip包处理类<br>
 * 创建者：XXX<br>
 * 创建日期：2015年5月7日 - 下午1:35:02<br>
 * 版本： V0.1 <br>
 * 修改者： <br>
 * 修改日期：<br>
 */
public class ZipUtil {

	public static void main(String[] args) {
		File zipfile = new File("d://zip//test.zip");
		List<String> list=new ArrayList<String>();
		list.add("D://zip//1");
		list.add("D://zip//2");
		zipFiles(list, zipfile);
	}
	/**
	 * 将指定的多个文件压入指定的文件目录中
	 * @param 指定文件
	 * @param 压缩后文件
	 */
	public static void zipFiles(List<String> srcfile, File zipfile) {
		byte[] buf = new byte[1024];
		try {
			// Create the ZIP file
			ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipfile));
			// Compress the files
			for (int i = 0; i < srcfile.size(); i++) {
				File file = new File(srcfile.get(i));
				FileInputStream in = new FileInputStream(file);
				// Add ZIP entry to output stream.
				out.putNextEntry(new ZipEntry(file.getName()));
				// Transfer bytes from the file to the ZIP file
				int len;
				while ((len = in.read(buf)) > 0) {
					out.write(buf, 0, len);
				}
				// Complete the entry
				out.closeEntry();
				in.close();
			}
			// Complete the ZIP file
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 将ZIP写入response
	 * */
	public static void downFile(HttpServletResponse response, String serverPath, String str) {
		try {
			String path = serverPath + str;
			File file = new File(path);
			if (file.exists()) {
				InputStream ins = new FileInputStream(path);
				BufferedInputStream bins = new BufferedInputStream(ins);// 放到缓冲流里面
				OutputStream outs = response.getOutputStream();// 获取文件输出IO流
				BufferedOutputStream bouts = new BufferedOutputStream(outs);
				response.setContentType("application/x-download");// 设置response内容的类型
				response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(str, "UTF-8"));// 设置头部信息
				int bytesRead = 0;
				byte[] buffer = new byte[8192];
				// 开始向网络传输文件流
				while ((bytesRead = bins.read(buffer, 0, 8192)) != -1) {
					bouts.write(buffer, 0, bytesRead);
				}
				bouts.flush();// 这里一定要调用flush()方法
				ins.close();
				bins.close();
				outs.close();
				bouts.close();
			} else {
				System.out.println("目录不存在！");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/** 
     * 删除目录下所有的文件; 
     * @param path 
     */  
    public static boolean deleteExcelPath(File file){  
        String[] files = null;  
        if(file != null){  
            files = file.list();  
        }  
        if(file.isDirectory()){  
            for(int i =0;i<files.length;i++){  
                boolean bol = deleteExcelPath(new File(file,files[i]));  
                if(bol){  
                    System.out.println("delete success--"+file.getPath()+"\\"+files[i]);  
                }else{  
                    System.out.println("delete fail --"+file.getPath()+"\\"+files[i]);  
                }  
            }  
        }  
        return file.delete();  
    }  
    	 /**
    	  * 
    	  * 功能描述：压缩文件 <br>
    	  * 创建者：XXX <br>
    	  * 创建日期： 2015年5月7日 - 下午1:35:18<br>
    	  * 版本： V0.1 <br>
    	  * 修改者： <br>
    	  * 修改日期：<br>
    	  * @param directory 指定压缩文件路径 压缩到同目录
    	  * @throws IOException<br>
    	  * void<br>
    	  */
    	 public static void zip(String directory) throws FileNotFoundException, IOException {
    		 zip("", null, directory);
    	 }
    	 
    	 /**
    	  * 
    	  * 功能描述：多个文件压缩到文件 <br>
    	  * 创建者：XXX <br>
    	  * 创建日期： 2015年5月7日 - 下午1:35:18<br>
    	  * 版本： V0.1 <br>
    	  * 修改者： <br>
    	  * 修改日期：<br>
    	  * @param directory 指定压缩文件路径 压缩到同目录
    	  * @throws IOException<br>
    	  * void<br>
    	  */
    	 public static void bitchZip(List<String> directorys) throws FileNotFoundException, IOException {
    		 zips("", null, directorys);
    	 }
    	 
    	 /**
    	  * 
    	  * 功能描述：压缩文件 <br>
    	  * 创建者：XXX <br>
    	  * 创建日期： 2015年5月7日 - 下午1:36:03<br>
    	  * 版本： V0.1 <br>
    	  * 修改者： <br>
    	  * 修改日期：<br>
    	  * @param zipFileName 压缩产生的zip包文件名--带路径,如果为null或空则默认按文件名生产压缩文件名
    	  * @param relativePath 相对路径，默认为空
    	  * @param directory 文件或目录的绝对路径
    	  * void<br>
    	  */
        public static void zip(String zipFileName, String relativePath,
                String directory) throws FileNotFoundException, IOException {
            String fileName = zipFileName;
            if (fileName == null || fileName.trim().equals("")) {
                File temp = new File(directory);
                if (temp.isDirectory()) {
                    fileName = directory + ".zip";
                } else {
                    if (directory.indexOf(".") > 0) {
                        fileName = directory.substring(0, directory.lastIndexOf("."))+ "zip";
                    } else {
                        fileName = directory + ".zip";
                    }
                }
            }
            ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(fileName));
            try {
                zip(zos, relativePath, directory);
            } catch (IOException ex) {
                throw ex;
            } finally {
                if (null != zos) {
                    zos.close();
                }
            }
        }
        
        /**
         * 
         * 功能描述：压缩文件 <br>
         * 创建者：XXX <br>
         * 创建日期： 2015年5月7日 - 下午1:36:03<br>
         * 版本： V0.1 <br>
         * 修改者： <br>
         * 修改日期：<br>
         * @param zipFileName 压缩产生的zip包文件名--带路径,如果为null或空则默认按文件名生产压缩文件名
         * @param relativePath 相对路径，默认为空
         * @param directory 文件或目录的绝对路径
         * void<br>
         */
        public static void zips(String zipFileName, String relativePath,
        		List<String> directorys) throws FileNotFoundException, IOException {
        	for(String directory:directorys){
        		String fileName = zipFileName;
            	if (fileName == null || fileName.trim().equals("")) {
            		File temp = new File(fileName);
            		if (temp.isDirectory()) {
            			fileName = directory + ".zip";
            		} else {
            			if (directory.indexOf(".") > 0) {
            				fileName = directory.substring(0, directory.lastIndexOf("."))+ "zip";
            			} else {
            				fileName = directory + ".zip";
            			}
            		}
            	}
            	ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(fileName));
            	try {
            		zip(zos, relativePath, directory);
            	} catch (IOException ex) {
            		throw ex;
            	} finally {
            		if (null != zos) {
            			zos.close();
            		}
            	}
        	}
        }

        /**
         * 
         * 功能描述：压缩文件 <br>
         * 创建者：XXX <br>
         * 创建日期： 2015年5月7日 - 下午1:37:55<br>
         * 版本： V0.1 <br>
         * 修改者： <br>
         * 修改日期：<br>
         * @param zos  压缩输出流
         * @param relativePath  相对路径
         * @param absolutPath  文件或文件夹绝对路径
         * @throws IOException<br>
         * void<br>
         */
	private static void zip(ZipOutputStream zos, String relativePath,
                String absolutPath) throws IOException {
            File file = new File(absolutPath);
            if (file.isDirectory()) {
               File[] files = file.listFiles();
                for (int i = 0; i < files.length; i++) {
                    File tempFile = files[i];
                    if (tempFile.isDirectory()) {
                       String newRelativePath = relativePath + tempFile.getName()
                                + File.separator;
                        createZipNode(zos, newRelativePath);
                        zip(zos, newRelativePath, tempFile.getPath());
                    } else {
                        zipFile(zos, tempFile, relativePath);
                    }
                }
            } else {
                zipFile(zos, file, relativePath);
           }
        }

        /**
         * 
         * 功能描述：压缩文件 <br>
         * 创建者：XXX <br>
         * 创建日期： 2015年5月7日 - 下午1:38:46<br>
         * 版本： V0.1 <br>
         * 修改者： <br>
         * 修改日期：<br>
         * @param zos  压缩输出流
         * @param file  文件对象
         * @param relativePath  相对路径
         * @throws IOException<br>
         * void<br>
         */
        private static void zipFile(ZipOutputStream zos, File file,
                String relativePath) throws IOException {
            ZipEntry entry = new ZipEntry(relativePath + file.getName());
           zos.putNextEntry(entry);
            InputStream is = null;
            try {
               is = new FileInputStream(file);
               int BUFFERSIZE = 2 << 10;
               int length = 0;
                byte[] buffer = new byte[BUFFERSIZE];
                while ((length = is.read(buffer, 0, BUFFERSIZE)) >= 0) {
                   zos.write(buffer, 0, length);
                }
                zos.flush();
                zos.closeEntry();
            } catch (IOException ex) {
                throw ex;
            } finally {
                if (null != is) {
                   is.close();
                }
            }
        }

        /**
         * 
         * 功能描述：创建目录 <br>
         * 创建者：XXX <br>
         * 创建日期： 2015年5月7日 - 下午1:39:12<br>
         * 版本： V0.1 <br>
         * 修改者： <br>
         * 修改日期：<br>
         * @param zos  zip输出流
         * @param relativePath  相对路径
         * @throws IOException<br>
         * void<br>
         */
        private static void createZipNode(ZipOutputStream zos, String relativePath)
                throws IOException {
            ZipEntry zipEntry = new ZipEntry(relativePath);
            zos.putNextEntry(zipEntry);
            zos.closeEntry();
       }
        /**
         * 
         * 功能描述：解压缩文件 <br>
         * 创建者：XXX <br>
         * 创建日期： 2015年5月7日 - 下午1:39:32<br>
         * 版本： V0.1 <br>
         * 修改者： <br>
         * 修改日期：<br>
         * @param zipFilePath   zip文件路径
         * @param targetPath    解压缩到的位置，如果为null或空字符串则默认解压缩到跟zip包同目录跟zip包同名的文件夹下
         * void<br>
         */
        public static void unzip(String zipFilePath, String targetPath) throws IOException {
            InputStream is = null;
            FileOutputStream fileOut = null; 
            File file = null;
            ZipFile zipFile = null;
            try {
                zipFile = new ZipFile(zipFilePath,"GBK");
                String directoryPath = "";
                if (null == targetPath || "".equals(targetPath)) {
                    directoryPath = zipFilePath.substring(0, zipFilePath.lastIndexOf("."));
                } else {
                    directoryPath = targetPath;
                }
                for(Enumeration<?> entries = zipFile.getEntries(); entries.hasMoreElements();){ 
                    ZipEntry entry = (ZipEntry)entries.nextElement(); 
                    file = new File(directoryPath+"/"+entry.getName()); 
                    if(entry.isDirectory()){ 
                        file.mkdirs(); 
                    }else{ 
                        //如果指定文件的目录不存在,则创建之. 
                        File parent = file.getParentFile(); 
                        if(!parent.exists()){ 
                            parent.mkdirs(); 
                        } 
                        is = zipFile.getInputStream(entry); 
                        fileOut = new FileOutputStream(file); 
                        int readLen = 0;
                        byte[] buffer = new byte[4096];
                        while ((readLen = is.read(buffer, 0, 4096)) >= 0) {
                        	fileOut.write(buffer, 0, readLen);
                        }
                        fileOut.close(); 
                        is.close(); 
                    }    
                } 
                zipFile.close();
            } catch (IOException ex) {
                throw ex;
            } finally {
                if(null != zipFile){
                    zipFile = null;
                }
                if (null != is) {
                    is.close();
                }
                if (null != fileOut) {
                	fileOut.close();
                }
            }
        }
        
        /**
         * 
         * 功能描述：生产文件 如果文件所在路径不存在则生成路径 <br>
         * 创建者：XXX <br>
         * 创建日期： 2015年5月7日 - 下午1:41:04<br>
         * 版本： V0.1 <br>
         * 修改者： <br>
         * 修改日期：<br>
         * @param fileName   文件名 带路径
         * @param isDirectory  是否为路径
         * @return<br>
         * File<br>
         */
        public static File buildFile(String fileName, boolean isDirectory) {
            File target = new File(fileName);
            if (isDirectory){
                target.mkdirs();
            } else {
                if (!target.getParentFile().exists()) {
                    target.getParentFile().mkdirs();
                    target = new File(target.getAbsolutePath());
                }
            }
            return target;
        } 
        
           private HttpServletRequest request;  
             
           private HttpServletResponse response;  
             
           private File file;  
              
            private String fileFileName;  
              
            private String fileContentType;  
              
            private String fileType;  
              
            private String fileSize;  
              
            protected void uploadFile(String floder,String realPath)throws Exception{  
                InputStream is = null;  
                OutputStream os = null;  
                try{  
                    if(file != null){  
                        String[] fnType = fileFileName.split("\\.");  
                        if(fileType.indexOf(fnType[1].toUpperCase())!=-1){  
                              
                            //getRequest().get  
                            File fileR = new File(realPath);  
                            if(!fileR.exists()){  
                                fileR.mkdirs();  
                            }  
                            fileR = new File(realPath,fileFileName);  
                            if(!fileR.exists()){  
                                fileR.createNewFile();  
                            }  
                            os = new FileOutputStream(fileR);  
                            is = new FileInputStream(file);  
                            byte[] b = new byte[1024*100];  
                            int length = 0;  
                            boolean tag = false;  
                            StringBuilder sbC = new StringBuilder();  
                            while((length=is.read(b))!=-1){  
                                if(length>Integer.parseInt(fileSize)){  
                                    tag = true;  
                                    fileR.delete();  
                                    break;  
                                }  
                                os.write(b,0,length);  
                                sbC.append(new String(b,0,length,"utf-8"));  
                            }  
                        }else{  
                        }  
                    }  
                }catch(Exception e){  
                    e.printStackTrace();  
                    throw e;  
                }finally{  
                    if(is != null){  
                        is.close();  
                    }  
                    if(os != null){  
                        os.close();  
                    }  
                }  
            }  
    }
